﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using NDK.Utils;
using System.ComponentModel;

namespace LightController
{
    [Serializable]
    public enum LightControlerChanel
    {
        SA = 0,
        SB,
        SC,
        SD,
        SE,
        SF,
        SG,
        SH
    };

    [Serializable]
    public class RseeLightController : ILightController
    {
        private static log4net.ILog m_Logger = log4net.LogManager.GetLogger("RseeLightController");
        //串口
        [NonSerialized]
        SerialPort _port = new SerialPort();
        //网口
        [NonSerialized]
        AsySockets asySocket = new AsySockets();
        private string ReceiveData = string.Empty;
        public string Name { get; set; }
        public string CommunicationAddress { get; set; }
        public int ChanelCount { get; set; } = 4;
        public List<LightChanel> ChanelList { get; set; } = new List<LightChanel>();
        public bool IsConnect
        {
            get
            {
                //bool? isConnected = false;
              //  isConnected = asySocket?.isSocketConnected();
                if (CommunicationAddress.Contains("."))
                {
                    if (Net_Handle == 0)
                    {
                        Status = $"控制器：{Name}({CommunicationAddress})，未连接！";
                        return false;
                    }
                    else
                    {
                        return true;
                    }

                    //if (isConnected != true)
                    //{
                    //    return false;
                    //}
                    //else
                    //{
                    //    return true;
                    //}
                }
                else
                {
                    //if (_port?.IsOpen == false || _port == null)
                    //{
                    //    Status = $"控制器：{Name}({CommunicationAddress})，未连接！";
                    //    return false;
                    //}

                    if (Com_Handle == 0)
                    {
                        Status = $"控制器：{Name}({CommunicationAddress})，未连接！";
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return true;
            }
        }


        uint Net_Handle = 0;//网口通信句柄

        int Com_Handle = 0;//串口通信句柄
        #region 方法

        private static readonly object _lock = new object();

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;
        [NonSerialized]
        private string status = string.Empty;
        public string Status
        {
            get
            {
                return status;
            }
            private set
            {
                status = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value.ToString()));
            }
        }

        private string id = string.Empty;
        public string ID
        {
            get
            {
                return id;
            }

            set
            {
                id = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel">光源通道</param>
        /// <param name="nLight">光源亮度(0-255有效)</param>
        /// <returns></returns>
        public bool WriteData(LightControlerChanel channel, int nLight)
        {
            lock (_lock)
            {

                if (IsConnect == false)
                {
                    return false;
                }
                int dChannel = 1;
                switch (channel)
                {
                    case LightControlerChanel.SA:
                        dChannel = 1;
                        break;
                    case LightControlerChanel.SB:
                        dChannel = 2;
                        break;
                    case LightControlerChanel.SC:
                        dChannel = 3;
                        break;
                    case LightControlerChanel.SD:
                        dChannel = 4;
                        break;
                    case LightControlerChanel.SE:
                        dChannel = 5;
                        break;
                    case LightControlerChanel.SF:
                        dChannel = 6;
                        break;
                    case LightControlerChanel.SG:
                        dChannel = 7;
                        break;
                    case LightControlerChanel.SH:
                        dChannel = 8;
                        break;
                    default:
                        break;
                }
                if (nLight < 0)
                {
                    nLight = 0;
                }
                if (nLight > 255)
                {
                    nLight = 255;
                }

                int RepeatTimes = 0;

            ReSend:

                if (1 != RseeControllerAPI.RseeController_PM_D_8TE_BRTSetChannel(Com_Handle, Net_Handle, dChannel, nLight))
                {
                    RepeatTimes++;
                    if (RepeatTimes <= 5)
                        goto ReSend;
                    else
                    {
                        Status = $"控制器执行光源设置{RepeatTimes}次，仍然执行错误！";
                        return false;
                    }
                }
                return true;

                #region old

#if false
                //string strSend = string.Format("0:D4", nLight) + "#";
                if (CommunicationAddress.Contains("."))
                {
                ReSend:

                    if (1 != RseeControllerAPI.RseeController_PM_D_8TE_BRTSetChannel(Com_Handle, Net_Handle, dChannel , nLight))
                    {
                        RepeatTimes++;
                        if (RepeatTimes <= 5)
                            goto ReSend;
                        else
                        {
                            Status = $"控制器接收消息{RepeatTimes}次，仍然超时！";
                            return false;
                        }
                    }
                    return true;

#if false
                    //asySocket.SendData(strSend);
                    //Status = $"控制器发送消息：{strSend}！";

                    //RepeatTimes++;
                    ////接收光源反馈值
                    //Thread.Sleep(10);
                    //bool isLightReceiveTimeOut = false;
                    //DateTime dt = DateTime.Now;
                    //while (ReceiveData == string.Empty || !strChannel.Contains(ReceiveData))
                    //{
                    //    if ((DateTime.Now - dt).TotalMilliseconds >= 5)
                    //    {
                    //        isLightReceiveTimeOut = true;
                    //        break;
                    //    }
                    //}

                    //if (isLightReceiveTimeOut)
                    //{
                    //    if (RepeatTimes <= 5)
                    //        goto ReSend;
                    //    else
                    //    {
                    //        Status = $"控制器接收消息{RepeatTimes}次，仍然超时！";
                    //        return false;
                    //    }
                    //}
                    //Status = $"控制器发送消息：{strSend}，{RepeatTimes}次,后收到消息：{ReceiveData}！";
                    //ReceiveData = string.Empty;
                    //return true;
#endif
                }
                else
                {
                ReSend1:
                    _port.WriteLine(strSend);
                    Status = $"控制器发送消息：{strSend}！";

                    RepeatTimes++;
                    //接收光源反馈值
                    Thread.Sleep(10);
                    bool isLightReceiveTimeOut = false;
                    DateTime dt = DateTime.Now;
                    while (ReceiveData == string.Empty || !strChannel.Contains(ReceiveData))
                    {
                        if ((DateTime.Now - dt).TotalMilliseconds >= 5)
                        {
                            isLightReceiveTimeOut = true;
                            break;
                        }
                    }

                    if (isLightReceiveTimeOut)
                    {
                        if (RepeatTimes <= 5)
                            goto ReSend1;
                        else
                        {
                            Status = $"控制器接收消息{RepeatTimes}次，仍然超时！";
                            return false;
                        }
                    }
                    Status = $"控制器发送消息：{strSend}，{RepeatTimes}次,后收到消息：{ReceiveData}！";
                    ReceiveData = string.Empty;
                    return true;
                }
#endif
                #endregion

            }
        }
        #endregion


        /// <summary>
        /// 关闭所有光源
        /// </summary>
        public bool CloseAllLight()
        {
            Status = $"控制器关闭所有通道！";
            for (int i = 0; i < ChanelCount; i++)
            {
                WriteData((LightControlerChanel)i, 0);
            }
            return true;
        }

        /// <summary>
        /// 打开所有光源
        /// </summary>
        public bool OpenAllLight()
        {
            Status = $"控制器打开所有通道！";
            for (int i = 0; i < ChanelCount; i++)
            {
                WriteData((LightControlerChanel)i, 255);
            }
            return true;
        }


        #region 通讯回调函数
        /// <summary>
        /// 串口回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string strReceiced = this.Read();

            try
            {
                if (strReceiced == string.Empty) { return; }
                strReceiced = strReceiced.Replace("\0", "");
                ReceiveData = strReceiced;
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 网口回调函数
        /// </summary>
        /// <param name="strReceiced"></param>
        void _onRecieveData(string strReceiced)
        {
            try
            {
                if (strReceiced == null) { return; }
                strReceiced = strReceiced.Replace("\0", "");
                ReceiveData = strReceiced;
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <returns>返回值：接受到数据</returns>
        public string Read()
        {
            try
            {
                string strTempValue = string.Empty;
                if (!_port.IsOpen) return "";
                strTempValue = _port.ReadExisting();
                return strTempValue;
            }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// 连接到光源控制器
        /// </summary>
        /// <returns></returns>
        public bool Connect()
        {
            try
            {
                Status = $"Connecting {Name} Controller:{CommunicationAddress}";
                if (CommunicationAddress.Contains("."))
                {
#if false
                    if (asySocket == null)
                    {
                        asySocket = new AsySockets();
                    }

                    if (asySocket?.isSocketConnected() == true)
                    {
                        Status = $"{Name} Controller:{CommunicationAddress} is Already Connected!";
                        return true;
                    }
                    asySocket.ConnectServer(CommunicationAddress, 8234);
                    asySocket.ReceiveDataCompleteEvent += new AsySockets.ReceiveDataCompleteHandler(_onRecieveData);
                    Status = $"Connected OPT Controller:{CommunicationAddress} Success！";
#endif
                    if (Net_Handle == 0)//句柄=0，未打开
                        Net_Handle = RseeControllerAPI.RseeController_ConnectNet(CommunicationAddress, 8234);
                    else
                    {
                        Status = $"{Name} Controller:{CommunicationAddress} is Already Connected!";
                        return true;
                    }

                    if (Net_Handle == 0)
                    {
                        Status = $"Connected OPT Controller:{CommunicationAddress} Fail！";
                        return false;
                    }
                    else
                    {
                        Status = $"Connected OPT Controller:{CommunicationAddress} Success！";
                        return true;
                    }
                }
                else
                {
                    string PortName = CommunicationAddress;
                    if (Com_Handle == 0)
                    {
                        Com_Handle = RseeControllerAPI.RseeController_OpenCom(PortName, 19200, true);
                        if (Com_Handle != 0)
                        {
                            Status = $"Connected {Name} Controller:{CommunicationAddress} Success！";
                            return true;
                        }
                        else
                        {
                            Status = $"Connected {Name} Controller:{CommunicationAddress} Fail！";
                            return false;
                        }
                    }
                    else
                    {
                        Status = $"{Name} Controller:{CommunicationAddress} is Already Connected!";
                        return true;
                    }
                }

#if false
                if (_port == null)
                {
                    _port = new SerialPort();
                }
                _port.PortName = CommunicationAddress;
                if (_port.IsOpen == true)
                {
                    Status = $"{Name} Controller:{CommunicationAddress} is Already Connected!";
                    return true;
                }

                string comParam = "19200,0,8,1,\r";
                string[] arg = comParam.Trim().Split(',');

                _port.BaudRate = int.Parse(arg[0].Trim());
                _port.Parity = (Parity)int.Parse(arg[1].Trim());
                _port.DataBits = int.Parse(arg[2].Trim());
                _port.StopBits = (StopBits)int.Parse(arg[3].Trim());
                _port.Handshake = Handshake.None;
                _port.DataReceived += new SerialDataReceivedEventHandler(_port_DataReceived);

#if DEBUG
                _port.ReadTimeout = 500; // DEBUG时 禁止COM端口读写超时
                _port.WriteTimeout = -1;
#else
                _port.ReadTimeout = 15000;// RELEASE 时COM端口读写超时为5秒
                _port.WriteTimeout = 15000;
#endif

                _port.Open(); // 打开端口
                Status = $"Connected {Name} Controller:{CommunicationAddress} Success！";

                return true;
#endif

            }
            catch (Exception ex)
            {
                Status = $"Controller:{CommunicationAddress} Connect failed,Exception：{ex.Message + ex.StackTrace}";
                throw new Exception($"Controller:{CommunicationAddress} Connect failed,Exception：{ex.Message + ex.StackTrace}");
            }
        }

        /// <summary>
        /// 断开光源控制器
        /// </summary>
        /// <returns></returns>
        public bool Disconnect()
        {
            try
            {
                if (CommunicationAddress.Contains("."))
                {
                    //asySocket?.Close();

                   RseeControllerAPI.RseeController_CloseNet(Net_Handle);
                    Net_Handle = 0;
                }
                else
                {
                    //_port?.Close();

                    RseeControllerAPI.RseeController_CloseCom(CommunicationAddress, Com_Handle);
                    Com_Handle = 0;
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 给指定通道号发送值
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="val"></param>
        public bool SetIntensity(int ch, int val)
        {
            return WriteData((LightControlerChanel)ch, val);
        }


        public bool SetMultiIntensity(List<int> chs, List<int> vals)
        {
            bool isSuccess = false;
            for (int i = 0; i < chs.Count; i++)
            {
                isSuccess &= WriteData((LightControlerChanel)chs[i], vals[i]);
            }
            return isSuccess;
        }

        public bool ReadIntensity(int ch, ref int val)
        {
            throw new NotImplementedException();
        }



        #endregion
    }
}

